package xin.pms.model;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.*;
import org.apache.commons.codec.digest.DigestUtils;
import org.hibernate.validator.constraints.NotBlank;
import xin.common.utils.AssertUtils;
import xin.core.jpa.JpaConstant;
import xin.core.jpa.model.AuditableEntity;
import xin.pms.enums.HashAlgorithm;

import javax.persistence.*;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashSet;
import java.util.List;

/**
 * <pre>
 * 用户模型
 * </pre>
 *
 * @author lixin_ma@outlook.com
 * @version 1.0
 * @since 2018/7/28 14:48
 */
@Entity
@Table(name = "pms_user")
@Builder
@AllArgsConstructor
@Data
@ToString(callSuper = true, exclude = { "passwordHash" ,"roles","permissions"})
@EqualsAndHashCode(callSuper = true, of = {})
public class User extends AuditableEntity implements Serializable {

    @NotBlank
    @Column(length = JpaConstant.NameColumnLength, unique = true)
    private String userName;

    @Column(length = JpaConstant.NameColumnLength)
    private String name;

    @Column(length = JpaConstant.CommonStringLength)
    private String mobile;

    @Column(length = JpaConstant.CommonStringLength)
    private String wechat;

    @Column(length = JpaConstant.CommonStringLength)
    private String mail;

    @Column(length = JpaConstant.CommonStringLength)
    private String idType;

    @Column(length = JpaConstant.CommonStringLength)
    private String idNum;

    @Column(length = JpaConstant.CommonStringLength)
    private String company;

    @Column(length = JpaConstant.CommonStringLength)
    private String department;

    @JsonIgnore
    @Column(length = 512)
    private String passwordHash;

    @JsonIgnore
    @Enumerated(EnumType.STRING)
    @Column(length = JpaConstant.HashStringLength)
    private HashAlgorithm algorithm;

    @JsonIgnore
    @Column(length = JpaConstant.CommonStringLength)
    private String salt;

    //@JsonDeserialize(using = LocalDateTimeDeserializer.class)
    //@JsonSerialize(using = LocalDateTimeSerializer.class)
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    @Column()
    private Date lastPasswordResetDate;



    /**
     * 角色
     */
    @JsonIgnore
    @ManyToMany(fetch = FetchType.LAZY, cascade = { CascadeType.MERGE})
    @OrderBy("priority desc")
    @JoinTable(name = "pms_role_user", joinColumns = {
            @JoinColumn(name = "user_id", nullable = false, updatable = false) }, inverseJoinColumns = {
            @JoinColumn(name = "role_id", nullable = false, updatable = false) })
    private List<Role> roles;

    /**
     * 权限
     */
    @JsonIgnore
    @ManyToMany(fetch = FetchType.LAZY, cascade = { CascadeType.MERGE})
    @OrderBy("priority desc")
    @JoinTable(name = "pms_user_permission", joinColumns = {
            @JoinColumn(name = "user_id", nullable = false, updatable = false) }, inverseJoinColumns = {
            @JoinColumn(name = "permission_id", nullable = false, updatable = false) })
    private List<Permission> permissions;

    @JsonIgnore
    @Transient
    private HashSet<Permission> allPermissions;

    @JsonIgnore
    @Transient
    private HashSet<Role> allRoles;

    public User(){
        this.locked = Boolean.FALSE;
        this.deleted = Boolean.FALSE;
    }


    public HashSet<Role> getAllRoles() {
        this.allRoles = new HashSet<>();
        List<Role> roles = this.getRoles();
        this.allRoles.addAll(roles);
        return allRoles;
    }

    public HashSet<Permission> getAllPermissions() {
        this.allPermissions = new HashSet<>();
        List<Permission> permissions = this.getPermissions();
        this.allPermissions.addAll(permissions);

        List<Role> roles = this.getRoles();
        if (AssertUtils.isNotNull(roles)) {
            for (Role role : roles) {
                this.allPermissions.addAll(role.getPermissions());
            }
        }
        return allPermissions;
    }


    public static void main(String [] args){
        String salt = "ax9hHM8VuW1SVmzvLzunJy6ct0z2HV6W";
        String hash = DigestUtils.sha512Hex(salt + "xin");
        System.out.println(">>>salt:" + salt);
        System.out.println(">>>hash:" + hash);
    }
}
